package com.lry.basic.spring.aop.core;

import com.lry.basic.spring.aop.face.Advisor;
import com.lry.basic.spring.aop.face.PointcutAdvisor;
import com.lry.basic.spring.ioc.BeanFactory;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author:刘仁有
 * @desc:
 * @email:953506233@qq.com
 * @data:2019/11/8
 */
public class AopProxyUtils {
    /**
     *
     * @param target 目标对象
     * @param method 目标方法
     * @param args 目标方法参数
     * @param matchAdvisors 匹配的切面
     * @param proxy cglib代理对象
     * @param beanFactory bean工厂
     * @return
     * @throws Exception
     */
    public static Object applyAdvices(Object target, Method method, Object[]args,
    List<Advisor>matchAdvisors, Object proxy, BeanFactory beanFactory) throws Exception {
        // 1、获取要对当前方法进行增强的advice ,before around after
        List<Object>advices = getShouldApplyAdvices(target.getClass(), method, matchAdvisors,
                beanFactory);
        if(advices.isEmpty()){
            return method.invoke(target,args);
        }else{
            // 责任链式执行增强
            AopAdviceChainInvocation chain = new AopAdviceChainInvocation(proxy, target, method, args, advices);
            return chain.invoke();
        }
    }

    public static List<Object> getShouldApplyAdvices(Class<?> beanClass, Method method, List<Advisor> matchAdvisors, BeanFactory beanFactory) throws Exception {
        if(matchAdvisors.isEmpty())return null;
        List<Object>advices = new ArrayList<>();
        for (Advisor advisor:matchAdvisors) {
            if(advisor instanceof PointcutAdvisor){
                if (((PointcutAdvisor) advisor).getPointcut().matchMethod(method, beanClass)) {
                    advices.add(beanFactory.getBean(advisor.getAdviceBeanName()));
                }
            }
        }
        return advices;
    }
}
